//
//  CLNavigationControllerStack.m
//  CLBrowser
//
//  Created by chuck on 2021/7/8.
//

#import "CLNavigationControllerStack.h"
#import "CLViewController.h"
#import "CLNavigationController.h"
#import "CLRouter.h"
#import "CLTabBarController.h"
@interface CLNavigationControllerStack()
@property (nonatomic, strong) id<CLViewModelServices> services;
@property (nonatomic, strong) NSMutableArray *navigationControllers;
@end
@implementation CLNavigationControllerStack

- (instancetype)initWithServices:(id<CLViewModelServices>)services {
    self = [super init];
    if (self) {
        self.services = services;
        self.navigationControllers = [[NSMutableArray alloc] init];
        [self registerNavigationHooks];
    }
    return self;
}

- (void)pushNavigationController:(CLNavigationController *)navigationController {
    
    if ([self.navigationControllers containsObject:navigationController]) return;
    
    [self.navigationControllers addObject:navigationController];
}

- (CLNavigationController *)popNavigationController {
    CLNavigationController *navigationController = [self topNavigationController];
    [self.navigationControllers removeLastObject];
    return navigationController;
}

- (CLNavigationController *)topNavigationController {
    CLNavigationController *navi = self.navigationControllers.lastObject;
    if (!navi) {
        UIWindow *window = [CLSharedAppDelegate getRootWindow];
        
        if ([window.rootViewController isKindOfClass:[CLNavigationController class]]) {
            return (CLNavigationController *)window.rootViewController;
        } else if ([window.rootViewController isKindOfClass:[UITabBarController class]]) {
            UIViewController *selectVc = [((UITabBarController *)window.rootViewController)selectedViewController];
            if ([selectVc isKindOfClass:[CLNavigationController class]]) {
                return (CLNavigationController *)selectVc;
            }
        } else if ([window.rootViewController isKindOfClass:[CLTabBarController class]]) {
            UIViewController *selectVc = [((CLTabBarController *)window.rootViewController).tabBarController selectedViewController];
            if ([selectVc isKindOfClass:[CLNavigationController class]]) {
                return (CLNavigationController *)selectVc;
            }
        }
    }
    return navi;
}

- (void)registerNavigationHooks {
    @weakify(self)
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(pushViewModel:animated:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        CLViewController *topViewController = (CLViewController *)[[self topNavigationController] topViewController];
        if (topViewController.tabBarController) {
            topViewController.snapshot = [topViewController.tabBarController.view snapshotViewAfterScreenUpdates:NO];
        } else {
            topViewController.snapshot = [[[self topNavigationController] view] snapshotViewAfterScreenUpdates:NO];
        }
        UIViewController *viewController = (UIViewController *)[CLRouter.sharedInstance viewControllerForViewModel:tuple.first];
        [[self topNavigationController] pushViewController:viewController animated:[tuple.second boolValue]];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(popViewModelAnimated:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [[self topNavigationController] popViewControllerAnimated:[tuple.first boolValue]];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(popToRootViewModelAnimated:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [[self topNavigationController] popToRootViewControllerAnimated:[tuple.first boolValue]];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(presentViewModel:animated:completion:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        UIViewController *viewController = (UIViewController *)[CLRouter.sharedInstance viewControllerForViewModel:tuple.first];
        
        CLNavigationController *presentingViewController = [self topNavigationController];
        if (![viewController isKindOfClass:CLNavigationController.class]) {
            viewController = [[CLNavigationController alloc] initWithRootViewController:viewController];
        }
        [self pushNavigationController:(CLNavigationController *)viewController];
        
        [presentingViewController presentViewController:viewController animated:[tuple.second boolValue] completion:tuple.third];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(dismissViewModelAnimated:completion:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        if ([CLRouter sharedInstance].currentVc.navigationController) {
            [CLNavigationService popControllerAnimated:[tuple.first boolValue]];
            return;
        }
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [self popNavigationController];
        [[self topNavigationController] dismissViewControllerAnimated:[tuple.first boolValue] completion:tuple.second];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(dismissViewControllerAnimated:completion:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        if ([CLRouter sharedInstance].currentVc.navigationController) {
            [CLNavigationService popControllerAnimated:[tuple.first boolValue]];
            return;
        }
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [self popNavigationController];
        [[self topNavigationController] dismissViewControllerAnimated:[tuple.first boolValue] completion:tuple.second];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(resetRootViewModel:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [self.navigationControllers removeAllObjects];
        /// VM映射VC
        UIViewController *viewController = (UIViewController *)[CLRouter.sharedInstance viewControllerForViewModel:tuple.first];
        if (![viewController isKindOfClass:[CLNavigationController class]] &&
            ![viewController isKindOfClass:[CLTabBarController class]]) {
            viewController = [[CLNavigationController alloc] initWithRootViewController:viewController];
            [self pushNavigationController:(CLNavigationController *)viewController];
        }
        CLSharedAppDelegate.window.rootViewController = viewController;
    }];
    /////// viewController
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(pushController:animated:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [self pushController:tuple.first animated:[tuple.second boolValue]];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(popControllerAnimated:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [self popControllerAnimated:[tuple.first boolValue]];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(popToRootControllerAnimated:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [self popToRootControllerAnimated:[tuple.first boolValue]];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(presentViewController:animated:completion:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [self presentViewController:tuple.first animated:[tuple.second boolValue] completion:tuple.third];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(dismissControllerAnimated:completion:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [[CLRouter sharedInstance].currentVc.view endEditing:YES];
        [self dismissControllerAnimated:[tuple.first boolValue] completion:tuple.second];
    }];
    
    [[(NSObject *)self.services
      rac_signalForSelector:@selector(resetRootController:)]
     subscribeNext:^(RACTuple *tuple) {
        @strongify(self);
        [self resetRootController:tuple.first];
    }];
}

- (void)pushController:(CLViewController *)viewController animated:(BOOL)animated{
    CLNavigationController *topNavi = [self topNavigationController];
    CLViewController *topViewController = (CLViewController *)[topNavi topViewController];
    
    if ([topViewController respondsToSelector:@selector(setSnapshot:)]) {
        if (topViewController.tabBarController) {
            topViewController.snapshot = [topViewController.tabBarController.view snapshotViewAfterScreenUpdates:NO];
        } else {
            topViewController.snapshot = [[topNavi view] snapshotViewAfterScreenUpdates:NO];
        }
    }
    
    if (topNavi) {
        [topNavi pushViewController:viewController animated:animated];
    } else {
        if (CLRouter.sharedInstance.currentVc.navigationController) {
            [CLRouter.sharedInstance.currentVc.navigationController pushViewController:viewController animated:animated];
        } else if (CLRouter.sharedInstance.currentVc) {
            [CLRouter.sharedInstance.currentVc presentViewController:viewController animated:animated completion:nil];
        } else {
            [CLSharedAppDelegate.window.rootViewController presentViewController:viewController animated:animated completion:nil];
        }
    }
}

- (void)popControllerAnimated:(BOOL)animated{
    [[self topNavigationController] popViewControllerAnimated:animated];
}

- (void)popToRootControllerAnimated:(BOOL)animated{
    [[self topNavigationController] popToRootViewControllerAnimated:animated];
}

- (void)presentViewController:(CLViewController *)viewController animated:(BOOL)animated completion:(VoidBlock _Nullable)completion{
    
    CLNavigationController *presentingViewController = [self topNavigationController];
    //    if (![viewController isKindOfClass:CLNavigationController.class]) {
    //        viewController = (CLViewController *)[[CLNavigationController alloc] initWithRootViewController:viewController];
    //    }
    if ([viewController isKindOfClass:CLNavigationController.class]) {
        [self pushNavigationController:(CLNavigationController *)viewController];
    }
    [presentingViewController presentViewController:viewController animated:animated completion:completion];
}

- (void)dismissControllerAnimated:(BOOL)animated completion:(VoidBlock _Nullable)completion{
    [self popNavigationController];
    [[self topNavigationController] dismissViewControllerAnimated:animated completion:completion];
}

- (void)resetRootController:(CLViewController *)viewController{
    [self.navigationControllers removeAllObjects];
    if (![viewController isKindOfClass:[CLNavigationController class]] &&
        ![viewController isKindOfClass:[CLTabBarController class]]) {
        viewController = (CLViewController *)[[CLNavigationController alloc] initWithRootViewController:viewController];
        [self pushNavigationController:(CLNavigationController *)viewController];
    }
    CLSharedAppDelegate.window.rootViewController = viewController;
}
@end
